package com.powernode.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Snowflake;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.powernode.clients.CartClient;
import com.powernode.clients.MemberClient;
import com.powernode.clients.ProductClient;
import com.powernode.constant.QueueConstant;
import com.powernode.domain.*;
import com.powernode.dto.OrderConfirmDto;
import com.powernode.mapper.OrderMapper;
import com.powernode.model.ShopOrder;
import com.powernode.service.OrderItemService;
import com.powernode.service.OrderService;
import com.powernode.utils.AuthUtil;
import com.powernode.vo.OrderStatus;
import com.powernode.vo.OrderVo;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService{
    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private MemberClient memberClient;

    @Autowired
    private ProductClient productClient;

    @Autowired
    private CartClient cartClient;

    @Autowired
    private Snowflake snowflake;

    @Autowired
    private OrderItemService orderItemService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Override
    public OrderStatus selectUserOrderStatus(String userId) {
        // 查询待支付数量
        Integer unPay = orderMapper.selectCount(new LambdaQueryWrapper<Order>()
                .eq(Order::getUserId, userId)
                .eq(Order::getDeleteStatus, 0)
                .eq(Order::getStatus, 1));

        // 待发货的数量
        Integer payed = orderMapper.selectCount(new LambdaQueryWrapper<Order>()
                .eq(Order::getUserId, userId)
                .eq(Order::getDeleteStatus, 0)
                .eq(Order::getStatus, 2));

        // 待收货
        Integer consignment = orderMapper.selectCount(new LambdaQueryWrapper<Order>()
                .eq(Order::getUserId, userId)
                .eq(Order::getDeleteStatus, 0)
                .eq(Order::getStatus, 3));

        return OrderStatus.builder().unPay(unPay).payed(payed).consignment(consignment).build();
    }

    @Override
    public OrderVo selectOrderConfirmInfo(String userId, OrderConfirmDto orderConfirmDto) {
        // 1.
        OrderVo orderVo = new OrderVo();

        // 2. 查询用户默认收获地址（远程调用）
        UserAddr userDefaultAddr = memberClient.getUserDefaultAddr(userId);
        orderVo.setUserAddr(userDefaultAddr);

        // 3. 判断订单确认页面来自于哪儿（商品详情页还是购物车）
        List<Long> basketIds = orderConfirmDto.getBasketIds();
        if (CollectionUtil.isEmpty(basketIds) || basketIds.size() == 0) {
            // 订单来自于商品详情页面
            productToConfirm(orderVo, orderConfirmDto.getOrderItem());
        } else {
            // 订单来自于购物车页面
            orderVo.setSource(1);
            cartToConfirm(orderVo, basketIds);
        }
        return orderVo;
    }

    /**
     * 提交订单
     * @param userId
     * @param orderVo
     * @return
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public String submitOrder(String userId, OrderVo orderVo) {
        // 1. 获取订单确认页面来源标识
        Integer source = orderVo.getSource();
        if (source.equals(1)) {
            // 来自购物车页面 -> 清楚购物车中购买的商品
            clearUserCart(userId, orderVo);
        }

        // 2. 修改商品prod和sku数量
        ChangeStock changeStock = changeProdAndSkuStock(orderVo);

        // 3. 生成全局唯一订单号
        String orderNum = generateOrderNum();

        // 4. 写订单和订单详情信息
        writeOrder(userId, orderNum, orderVo);

        // 5. 将商品修改的库存数量消息存放到消息队列
        sendMsg(orderNum, changeStock);

        return orderNum;
    }

    /**
     * 修改订单状态及数据的回滚
     * @param order
     * @param changeStock
     */
    @Override
    public void orderRollBack(Order order, ChangeStock changeStock) {
        // 修改订单状态
        order.setStatus(6);
        order.setCloseType(1);
        order.setUpdateTime(new Date());
        order.setFinallyTime(new Date());
        orderMapper.updateById(order);

        // 回滚商品购买的数量
        List<SkuChange> skuChangeList = changeStock.getSkuChangeList();
        skuChangeList.forEach(skuChange -> {
            skuChange.setCount(skuChange.getCount() * -1);
        });

        List<ProdChange> prodChangeList = changeStock.getProdChangeList();
        prodChangeList.forEach(prodChange -> {
            prodChange.setCount(prodChange.getCount() * -1);
        });

        // 远程调用
        productClient.changeStock(changeStock);
    }

    /**
     * 发送消息到消息队列
     * @param orderNum
     * @param changeStock
     */
    private void sendMsg(String orderNum, ChangeStock changeStock) {
        // 将数据转换为json数据格式存放在消息队列中
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("orderNum", orderNum);
        jsonObject.put("changeStock", changeStock);

        rabbitTemplate.convertAndSend(QueueConstant.ORDER_MS_QUEUE,jsonObject.toJSONString());
    }

    private void writeOrder(String userId, String orderNum, OrderVo orderVo) {
        // 1. 获取订单店铺集合
        List<ShopOrder> shopOrderList = orderVo.getShopCartOrders();

        List<BigDecimal> allOneSkuTotalAmounts = new ArrayList<>();
        ArrayList<Integer> allOneSkuTotalCounts = new ArrayList<>();
        StringBuffer sb = new StringBuffer();
        ArrayList<OrderItem> orderItems = new ArrayList<>();

        // 2
        shopOrderList.forEach(shopOrder -> {
            List<OrderItem> orderItemList = shopOrder.getShopCartItemDiscounts();
            orderItemList.forEach(orderItem -> {
                // 完善订单商品
                orderItem.setOrderNumber(orderNum);
                orderItem.setUserId(userId);

                // 单个sku prod的总金额
                BigDecimal productTotalAmount = orderItem.getProductTotalAmount();
                allOneSkuTotalAmounts.add(productTotalAmount);

                // 单个商品购买数量
                Integer prodCount = orderItem.getProdCount();
                allOneSkuTotalCounts.add(prodCount);

                sb.append(orderItem.getProdName()).append(",");

                orderItems.add(orderItem);
            });
        });

        // 3. 生成订单和订单详细信息

        // 4. 批量生成订单详情信息
        if (!orderItemService.saveBatch(orderItems)) {
            throw new RuntimeException("服务器开小差了");
        }

        // 4. 组装订单总览
        Order order = new Order();
        order.setProdName(sb.toString());
        order.setUserId(userId);
        order.setOrderNumber(orderNum);
        BigDecimal total = allOneSkuTotalAmounts.stream().reduce(new BigDecimal(0), BigDecimal::add);
        order.setTotal(total);
        order.setActualTotal(total);
        order.setFreightAmount(new BigDecimal(0));
        if (total.compareTo(new BigDecimal(99)) == -1) {
            order.setActualTotal(total.add(new BigDecimal(6)));
            order.setFreightAmount(new BigDecimal(6));
        }

        order.setPayType(1);
        order.setRemarks(orderVo.getRemarks());
        order.setStatus(1);
        order.setAddrOrderId(orderVo.getUserAddr().getAddrId());
        order.setProductNums(allOneSkuTotalCounts.stream().reduce(0, Integer::sum));
        order.setCreateTime(new Date());
        order.setUpdateTime(new Date());
        order.setIsPayed(0);
        order.setDeleteStatus(0);
        order.setRefundSts(0);

        int insert = orderMapper.insert(order);
        if (insert <= 0) {
            throw new RuntimeException("服务器开小差了");
        }
    }

    private String generateOrderNum() {
        return snowflake.nextIdStr();
    }

    /**
     * 修改商品prod和sku库存数量
     * @param orderVo
     * @return
     */
    private ChangeStock changeProdAndSkuStock(OrderVo orderVo) {
        ChangeStock changeStock = new ChangeStock();
        // 获取店铺集合对象
        List<ShopOrder> shopCartOrders = orderVo.getShopCartOrders();


        //
        ArrayList<SkuChange> skuChanges = new ArrayList<>();
        ArrayList<ProdChange> prodChanges = new ArrayList<>();

        // 循环店铺集合对象
        shopCartOrders.forEach(shopOrder -> {
            // 从店铺中获取商品条目集合对象
            List<OrderItem> orderItemList = shopOrder.getShopCartItemDiscounts();

            // 循环遍历商品条目集合或商品条目
            orderItemList.forEach(orderItem -> {
                // 获取商品
                Long prodId = orderItem.getProdId();
                Long skuId = orderItem.getSkuId();
                Integer prodCount = orderItem.getProdCount();

                // 判断当前orderItem中的商品prodId和prodChangeList中的商品有一致的
                List<ProdChange> targetProdChanges = prodChanges.stream()
                        .filter(prodChange -> prodChange.getProdId().equals(orderItem.getProdId()))
                        .collect(Collectors.toList());

                if (CollectionUtil.isEmpty(targetProdChanges) || targetProdChanges.size() == 0) {
                    ProdChange prodChange = new ProdChange();
                    prodChange.setProdId(prodId);
                    prodChange.setCount(prodCount*(-1));
                    prodChanges.add(prodChange);
                } else {
                    ProdChange prodChange = targetProdChanges.get(0);
                    prodChange.setProdId(prodId);
                    prodChange.setCount(prodChange.getCount() * -1 + prodCount*(-1));
                }

                SkuChange skuChange = new SkuChange();
                skuChange.setSkuId(skuId);
                skuChange.setCount(prodCount*(-1));
                skuChanges.add(skuChange);



            });
        });

        changeStock.setProdChangeList(prodChanges);
        changeStock.setSkuChangeList(skuChanges);

        // 远程调用，修改商品prod和sku库存数量
        productClient.changeStock(changeStock);

        return changeStock;
    }

    /**
     * 清楚用户购物车
     * @param userId
     * @param orderVo
     */
    private void clearUserCart(String userId, OrderVo orderVo) {
        // 获取商品skuId集合

        // 获取订单店铺集合对象
        List<ShopOrder> shopOrders = orderVo.getShopCartOrders();

        //
        ArrayList<Long> skuIds = new ArrayList<>();

        // 获取商品条目
        shopOrders.forEach(shopOrder -> {
            // 从店铺对象中获取商品条目集合
            List<OrderItem> orderItems = shopOrder.getShopCartItemDiscounts();

            // 循环遍历商品条目集合对象
            orderItems.forEach(orderItem -> {
                // 拿到商品skuId
                Long skuId = orderItem.getSkuId();
                skuIds.add(skuId);
            });
        });

        // 删除购物车中的商品(远程调用)
        if (!cartClient.clearBasketSkuList(skuIds, userId)) {
            throw new RuntimeException("服务器开小差了");
        }

    }

    private void cartToConfirm(OrderVo orderVo, List<Long> basketIds) throws RuntimeException {
        // 1. 根据购物车id集合查询购物车对象集合
        List<Basket> basketList= cartClient.getBasketsByIds(basketIds);

        if (CollectionUtil.isEmpty(basketList) || basketList.size() == 0) {
            throw new RuntimeException("服务器开小差了");
        }

        // 2. 从购物车对象集合获取商品sku集合
        List<Long> skuIds = basketList.stream().map(item -> item.getSkuId()).collect(Collectors.toList());

        // 3. 根据skuid集合查询sku对象集合
        List<Sku> skuList = productClient.getSkuListBySkuIds(skuIds);
        if (CollectionUtil.isEmpty(skuList) || skuList.size() == 0) {
            throw new RuntimeException("服务器开小差了");
        }

        // 4. 组装数据, 分组
        Map<Long, List<Basket>> allShopOrderMap = basketList.stream().collect(Collectors.groupingBy(Basket::getShopId));

        ArrayList<ShopOrder> shopOrders = new ArrayList<>();

        ArrayList<BigDecimal> allOneSkuTotalAmounts = new ArrayList<>();

        ArrayList<Integer> allCounts = new ArrayList<>();

        // 5. 循环遍历map集合
        allShopOrderMap.forEach((shopId, baskets) -> {
            ShopOrder shopOrder = new ShopOrder();
            ArrayList<OrderItem> orderItems = new ArrayList<>();
            // 循环遍历当前店铺中的购物车记录
            for (Basket basket:baskets) {
                // 创建订单商品条目对象
                OrderItem orderItem = new OrderItem();

                // 将购物车对象中属性拷贝到商品条目对象
                BeanUtils.copyProperties(basket, orderItem);

                // 从商品sku集合过滤出当前购物车中skuId一致的商品对象
                Sku sku = skuList.stream()
                        .filter(sku_ -> sku_.getSkuId().equals(basket.getSkuId()))
                        .collect(Collectors.toList()).get(0);
                BeanUtils.copyProperties(sku, orderItem);

                //
                orderItem.setUserId(AuthUtil.getLoginUserId());

                //
                orderItem.setRecTime(new Date());

                //
                orderItem.setCommSts(0);


                Integer basketCount = basket.getBasketCount();
                allCounts.add(basketCount);
                orderItem.setProdCount(basketCount);

                // 计算单个商品总额
                BigDecimal total = sku.getPrice().multiply(new BigDecimal(basketCount));
                orderItem.setProductTotalAmount(total);
                allOneSkuTotalAmounts.add(total);

                orderItems.add(orderItem);
            }

            shopOrder.setShopCartItemDiscounts(orderItems);

            shopOrders.add(shopOrder);
        });


        // 计算总数量
        Integer totalCount = allCounts.stream().reduce(0, Integer::sum);

        // 所有商品总金额
        BigDecimal amount = allOneSkuTotalAmounts.stream().reduce(new BigDecimal(0), BigDecimal::add);

        orderVo.setTotalCount(totalCount);
        orderVo.setTotal(amount);
        orderVo.setActualTotal(amount);

        if (amount.compareTo(new BigDecimal(99)) == -1) {
            orderVo.setTransfee(new BigDecimal(6));
            orderVo.setActualTotal(amount.add(new BigDecimal(6)));
        }


        orderVo.setShopCartOrders(shopOrders);
    }

    private void productToConfirm(OrderVo orderVo, OrderItem orderItem) {

        // 1. 设置商品数量
        Integer prodCount = orderItem.getProdCount();
        orderVo.setTotalCount(prodCount);

        // 获取商品skuId
        Long skuId = orderItem.getSkuId();
        List<Sku> skuList = productClient.getSkuListBySkuIds(Collections.singletonList(skuId));
        if (CollectionUtil.isEmpty(skuList) || skuList.size() == 0) {
            throw new RuntimeException("服务器开小差了");
        }
        Sku sku = skuList.get(0);

        // 2. 设置合计
        BigDecimal price = sku.getPrice();
        BigDecimal total = price.multiply(new BigDecimal(prodCount));
        orderVo.setTotal(total);
        orderVo.setActualTotal(total);

        // 3. 计算运费和小计
        if (total.compareTo(new BigDecimal(99)) == -1) {
            orderVo.setTransfee(new BigDecimal(6));
            orderVo.setActualTotal(new BigDecimal(6).add(total));
        }

        // 4. 创建店铺对象
        ArrayList<ShopOrder> shopOrders = new ArrayList<>();
        ShopOrder shopOrder = new ShopOrder();
        ArrayList<OrderItem> orderItems = new ArrayList<>();



        // 将商品sku对象中的属性拷贝到商品条目对象中

        BeanUtils.copyProperties(sku, orderItem);
        orderItem.setUserId(AuthUtil.getLoginUserId());
        orderItem.setProductTotalAmount(total);
        orderItem.setRecTime(new Date());
        orderItem.setCommSts(0);

        orderItems.add(orderItem);
        shopOrder.setShopCartItemDiscounts(orderItems);
        shopOrders.add(shopOrder);
        orderVo.setShopCartOrders(shopOrders);


    }
}
